package com.product.statemachine.common;

import com.product.statemachine.common.event.StateEvent;
import com.product.statemachine.common.exception.StateMachineException;
import com.product.statemachine.common.executor.DomainStateEventExecutor;
import com.product.statemachine.common.state.State;
import lombok.Data;
import lombok.Getter;
import lombok.Setter;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;

import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;

/**
  * @author: caoxingming
  * @data: 2022/6/9 12:03 下午
  * @description: 事件状态机环境变量类
  **/
@Component
@Data
@Getter
@Setter
public class DomainStateMachineEnvironment {

    /**
     * 已开启的状态机名称集合
     */
    private List<String> domainStateMachineNamesInOperate = new ArrayList<>(10);

    /**
     * 已开启的状态机事件 Map
     * key: machineName
     * value:
     *      HashMap<String,StateEvent>
     *                      key:stateEventName
     *                      value:StateEvent 对象
     */
    private HashMap<String, HashMap<String,StateEvent>> stateEventHashMap = new HashMap<>();

    /**
     * 已开启的状态机状态 Map
     * key: machineName
     * value:
     *      HashMap<String,State>
     *                key:StateName
     *                value:State 对象
     */
    private HashMap<String, HashMap<String,State>> stateHashMap= new HashMap<>();


    /**
     * 已开启的状态机执行器 Map
     * key: machineName
     * value:
     *      HashMap<String,State>
     *                 key:stateEvent Class全路径
     *                 value:DomainStateEventExecutor 对象
     */
    private HashMap<String,HashMap<String,DomainStateEventExecutor>> domainStateEventExecutors= new HashMap<>();


    public Boolean isInOperateStateMachineExists() {
        if(CollectionUtils.isEmpty(domainStateMachineNamesInOperate)) {
            return false;
        }
        return true;
    }


    /**
     * 检查状态机环境变量
     */
    public void checkDomainStateMachineEnvironment() {

        /**
         * 检查状态机事件
         *      同一个状态机的事件,不允许重复
         *      不同状态机的事件,不允许重复
         */
        HashMap<String, HashMap<String, StateEvent>> stateEventHashMap = this.getStateEventHashMap();
        List<StateEvent> stateEvents = new ArrayList<>();
        Collection<HashMap<String, StateEvent>> stateEventCollection = stateEventHashMap.values();
        stateEventCollection.stream().forEach(value->{
            stateEvents.addAll(value.values());
        });
        long count = stateEvents.stream().distinct().count();
        if(count != stateEvents.size()) {
            throw new StateMachineException("存在重复 stateEvent!");
        }


        /**
         *  检查状态机状态
         *      同一个状态机的状态,不允许重复
         *      不同状态机的状态,不允许重复
         */
        HashMap<String, HashMap<String, State>> stateHashMap = this.getStateHashMap();
        List<State> states = new ArrayList<>();
        Collection<HashMap<String, State>> values = stateHashMap.values();
        values.stream().forEach(value->{
            states.addAll(value.values());
        });
        if(states.stream().distinct().count() != states.size()) {
            throw new StateMachineException("存在重复 state!");
        }


        /**
         *  检查状态机执行器
         *      同一个状态机的执行器,不允许重复
         *      不同状态机的执行器,不允许重复
         */
        HashMap<String, HashMap<String, DomainStateEventExecutor>> executorHashMap = this.getDomainStateEventExecutors();
        List<DomainStateEventExecutor> executors = new ArrayList<>();
        Collection<HashMap<String, DomainStateEventExecutor>> executorCollection = executorHashMap.values();
        executorCollection.stream().forEach(value->{
            executors.addAll(value.values());
        });
        if(executors.stream().distinct().count() != executors.size()) {
            throw new StateMachineException("存在重复 executors!");
        }

    }



}
